import random
from logging import Logger

from task_service.task_context import StorerDeliverLayer
from x_pc.db.command.model import CommandRoute
from x_pc.db.sf_data import Sku
from x_pc.db.source.model import DeliveryWorkQueue, InteriorWorkQueue, PreworkWorkQueue
from x_pc.model.model import PackType, CommandTypeCode


def delivery_route_choice(rt: DeliveryWorkQueue, route_list: list[CommandRoute], logger: Logger,
                          nosplit_set: set | None, split_set: set | None, storer_layer: StorerDeliverLayer,
                          do_not_fix_pack_type_set: set[tuple[str, str]],
                          all_dc_lpns_set: set[tuple[str, str]],
                          all_dc_lpns_dict: dict[tuple[str, str], list[tuple[str, str, int]]]):
    """
    发货 路由选择
    :param rt:
    :param route_list:
    :param logger:
    :param nosplit_set:
    :param split_set:
    :param storer_layer:
    :param do_not_fix_pack_type_set:
    :param all_dc_lpns_set:
    :param all_dc_lpns_dict:
    :return:
    """
    # 指令类型
    command_type_code: str = rt.command_type_code
    # 开始包装类型
    start_pack_type: int = rt.origin_pack_type
    # 结束包装类型
    end_pack_type: int = rt.target_pack_type
    # 开始PCS数(实际)
    act_num: int = rt.act_num
    origin_sku_num = rt.origin_sku_num
    # 最终PCS数
    target_sku_num: int = rt.target_sku_num
    # 每件箱PCS数
    casecant: float = rt.casecant
    # dc lpn
    dc_lpn = (rt.command_group_code, rt.lpn)
    #
    match_route = []
    # 优先校验一下 自制存在一种场景：符合特定条件的，可直接件箱出
    pre_matched = False
    # 多DC 需拣选
    ext_force_gtp = hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp')

    # 全局过滤路径 仅保留 发货路径 (PICK_INTEGRATE)
    route_list = [r for r in route_list if r.command_type_code == command_type_code]

    # [场景] 实发实 且 需要拣选
    cond_real_and_need_pick = rt.deliver_factory and rt.deliver_factory == 'REAL' and (
            (dc_lpn not in all_dc_lpns_dict and act_num > target_sku_num) or (
            dc_lpn in all_dc_lpns_dict and ext_force_gtp)
    )
    # [场景] PKD
    cond_pkd = rt.template_id and rt.template_id == 'PKD'
    # [场景] PTX
    cond_ptx = rt.template_id and rt.template_id == 'PTX'

    # [ 非PKD场景 / 非PTX场景 / 非实发实拣选] 进行remark过滤
    if not (cond_pkd or cond_ptx or cond_real_and_need_pick):
        route_list = [r for r in route_list if r.remark == storer_layer.flag()]

    # Real 实发实的路径匹配 (任务标记为REAL 且 需要拣选)
    if cond_real_and_need_pick:
        pre_matched = True
        match_route = [r for r in route_list if r.remark == 'REAL' and r.start_pack_type == start_pack_type]
        if not match_route:
            warning_msg = f'[PC] task: {rt.task_id} REAL路径匹配，找不到路径'
            logger.warning(warning_msg)
    else:
        route_list = [r for r in route_list if r.remark != 'REAL']

    # 特殊路径匹配 (栈板拣料) PKD专属 [任务的template_id = PKD] -> 匹配[carry_type 带PKD]的路径
    if not pre_matched and rt.template_id and rt.template_id == 'PKD':
        pre_matched = True
        match_route = [r for r in route_list if r.carry_type == 'PKD']
        if not match_route:
            warning_msg = f'[PC] task: {rt.task_id} PKD路径匹配，找不到路径'
            logger.warning(warning_msg)
    else:
        route_list = [r for r in route_list if r.carry_type != 'PKD']

    # 特殊路径匹配 PTX专属 [任务的template_id = PTX] -> 匹配[carry_type 带PTX]的路径
    if not pre_matched and rt.template_id and rt.template_id == 'PTX':
        pre_matched = True
        match_route = [r for r in route_list if r.carry_type == 'PTX']
        if not match_route:
            warning_msg = f'[PC] task: {rt.task_id} PTX路径匹配，找不到路径'
            logger.warning(warning_msg)
    else:
        route_list = [r for r in route_list if r.carry_type != 'PTX']

    # 除 REAL+拣选, PKD, PTX 外的逻辑
    """
    0.满足整出条件【act_num=sum(target_num)】，按交付对象匹配1-1的栈板直出路径，不满足整出的再判断以下1和2
    1. sku属于非拆包
        1.1  就修正为1-2，按交付对象匹配1-2的NOSPLIT路径
    2. 其他
        2.1  按交付对象匹配1-3路径
    """
    if not pre_matched and start_pack_type == PackType.ZB.value:
        pre_matched = True
        match_route = [r for r in route_list if r.start_pack_type == PackType.ZB.value]
        # 整出 1-1栈板直出 (非多DC act_num == target_sku_num) or (多DC 无需拣选)
        if (dc_lpn not in all_dc_lpns_dict and act_num == target_sku_num) or (
                dc_lpn in all_dc_lpns_dict and not ext_force_gtp):
            match_route = [r for r in match_route if
                           r.end_pack_type == PackType.ZB.value and not r._carry_type and r.remark == storer_layer.flag()]
        elif nosplit_set and Sku.gen_uk(rt.sku) in nosplit_set:
            if end_pack_type != PackType.ZX.value:
                rt.target_pack_type = PackType.ZX.value
                warning_msg = f'[PC] 任务包规修正 (REAL+拣选, PKD, PTX -> sku属于非拆包) task: {rt.task_id}, target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                logger.warning(warning_msg)
                end_pack_type = PackType.ZX.value
            match_route = [r for r in match_route if
                           r.end_pack_type == end_pack_type and r.carry_type == 'NOSPLIT' and r.remark == storer_layer.flag()]
        else:
            match_route = [r for r in match_route if
                           r.end_pack_type == PackType.ZZX.value and r.remark == storer_layer.flag()]

    # 一楼 自制 直接出栈板场景
    if not pre_matched and storer_layer.is_zz() and storer_layer.is_f1() and end_pack_type == PackType.ZB.value:
        pre_matched = True
        for r in route_list:
            if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type and r.end_pack_type == end_pack_type:
                if r.remark == storer_layer.flag():
                    match_route.append(r)
        if not match_route:
            warning_msg = f'[PC] task: {rt.task_id} 一楼自制 直出栈板场景，找不到路径'
            logger.warning(warning_msg)

    # 自制(1/-1)+件箱 默认不换包，只有规定了自制换包的件箱 才走换包
    if not pre_matched and storer_layer.is_zz() and start_pack_type == PackType.ZX.value:
        uk = Sku.gen_uk(rt.sku)
        # 自制 需要拆包场景
        if uk in split_set:
            pre_matched = True
            if end_pack_type != PackType.ZZX.value:
                rt.target_pack_type = PackType.ZZX.value
                warning_msg = f'[PC] 任务包规修正 (自制SPLIT场景) task: {rt.task_id}, target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                logger.warning(warning_msg)
                end_pack_type = PackType.ZZX.value
            need_gpt = origin_sku_num != target_sku_num
            for r in route_list:
                if r.carry_type:
                    continue
                if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type and r.end_pack_type == end_pack_type:
                    if need_gpt:
                        if r.is_mpq != '1':
                            continue
                    else:
                        if r.is_mpq == '1':
                            continue
                    if r.remark == storer_layer.flag():
                        match_route.append(r)
            if not match_route:
                warning_msg = f'[PC] task: {rt.task_id} sku: {rt.sku} [sku SPLIT] 在自制出纸箱场景。start_pack_type: {start_pack_type}, end_pack_type: {PackType.ZX.value} 找不到路径'
                logger.warning(warning_msg)

    # 自制出纸箱场景
    if not pre_matched and storer_layer.is_zz() and nosplit_set:
        uk = Sku.gen_uk(rt.sku)
        if uk in nosplit_set:
            pre_matched = True
            for r in route_list:
                if r.carry_type != 'NOSPLIT':
                    continue
                # 修正纸箱直发，最终包规为纸箱
                if start_pack_type == PackType.ZX.value and end_pack_type != PackType.ZX.value:
                    # 实发实 无需修正
                    if rt.deliver_factory == 'REAL':
                        continue
                    rt.target_pack_type = PackType.ZX.value
                    warning_msg = f'[PC] 任务包规修正 (自制NOSPLIT场景) task: {rt.task_id}, target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                    logger.warning(warning_msg)
                    end_pack_type = PackType.ZX.value
                if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type and r.end_pack_type == end_pack_type:
                    if r.remark == storer_layer.flag():
                        match_route.append(r)
            if not match_route:
                warning_msg = f'[PC] task: {rt.task_id} sku: {rt.sku} [sku NO SPLIT] 在自制出纸箱场景。start_pack_type: {start_pack_type}, end_pack_type: {PackType.ZX.value} 找不到路径'
                logger.warning(warning_msg)
        else:
            route_list = [r for r in route_list if r.carry_type != 'NOSPLIT']

    # EMS出件箱、自制箱 直发(NOSPLIYT 无需拆箱) 场景
    if not pre_matched and not storer_layer.is_zz() and nosplit_set and start_pack_type in (
            PackType.ZX.value, PackType.ZZX.value):
        uk = Sku.gen_uk(rt.sku)
        if uk in nosplit_set:
            pre_matched = True
            for r in route_list:
                if r.command_type_code == command_type_code and r.start_pack_type == PackType.ZX.value and r.end_pack_type == PackType.ZX.value:
                    if not r.is_zz() and r.carry_type == 'NOSPLIT':
                        match_route.append(r)
            # 尝试 修正包规
            if start_pack_type == PackType.ZX.value and end_pack_type != PackType.ZX.value:
                rt.target_pack_type = PackType.ZX.value
                warning_msg = f'[PC] 任务包规修正 (1楼NOSPLIT场景) task: {rt.task_id}, target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                logger.warning(warning_msg)
            if not match_route:
                warning_msg = f'[PC] task: {rt.task_id} sku: {rt.sku} [sku NO SPLIT] 在EMS出纸箱、自制箱场景。start_pack_type: {start_pack_type}, end_pack_type: {PackType.ZX.value} 找不到路径'
                logger.warning(warning_msg)
        else:
            route_list = [r for r in route_list if r.carry_type != 'NOSPLIT']

    # 单任务 多DC场景: 1.要么被前面的NOSPLIT匹配; 2.要么被这边匹配到 直接去GTP拣选
    if not pre_matched:
        # 多DC 且 单任务
        if dc_lpn in all_dc_lpns_dict and len(all_dc_lpns_dict[dc_lpn]) == 1:
            pre_matched = True
            match_route = [_ for _ in route_list if
                           _.command_type_code == command_type_code and _.start_pack_type == start_pack_type and _.is_mpq == '1' and _.remark == storer_layer.flag()]
            # 尝试修正下包规
            if start_pack_type == PackType.ZX.value and end_pack_type == PackType.ZX.value:
                rt.target_pack_type = PackType.ZZX.value
                warning_msg = f'[PC] 任务包规修正 (多DC单任务场景) task: {rt.task_id}, target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                logger.warning(warning_msg)
            if not match_route:
                warning_msg = f'[PC] task: {rt.task_id} sku: {rt.sku} [单任务多DC] GTP场景 storer_layer: {storer_layer.flag()}, start_pack_type: {start_pack_type},  找不到路径'
                logger.warning(warning_msg)

    # 通用匹配逻辑  当没有预先匹配时，走该逻辑
    if not pre_matched:
        # 修正 起始包规为2 但起/始PCS数不同场景
        if start_pack_type == PackType.ZX.value and act_num != target_sku_num and (
                (rt.command_group_code, rt.task_id) not in do_not_fix_pack_type_set):
            # 非自制场景
            if end_pack_type != PackType.ZZX.value and not storer_layer.is_zz():
                rt.target_pack_type = PackType.ZZX.value
                warning_msg = f'[PC] 任务包规修正 (纸箱需拣选场景) task: {rt.task_id} target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                logger.warning(warning_msg)
                end_pack_type = PackType.ZZX.value
            # 自制场景
            if storer_layer.is_zz():
                #
                if origin_sku_num != target_sku_num or (hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp')):
                    if end_pack_type != PackType.ZZX.value:
                        rt.target_pack_type = PackType.ZZX.value
                        warning_msg = f'[PC] 任务包规修正 (自制 有拣选量场景) task: {rt.task_id} target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                        logger.warning(warning_msg)
                        end_pack_type = PackType.ZZX.value
                else:
                    if end_pack_type != PackType.ZX.value:
                        rt.target_pack_type = PackType.ZX.value
                        warning_msg = f'[PC] 任务包规修正 (自制 非SPLIT 默认不换包) task: {rt.task_id} target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                        logger.warning(warning_msg)
                        end_pack_type = PackType.ZX.value
        # 纸箱 自制1楼 多DC场景。默认不换包直发
        if storer_layer.is_zz() and storer_layer.is_f1() and start_pack_type == PackType.ZX.value and dc_lpn in all_dc_lpns_set:
            # 排除有 拣选量场景
            if not (origin_sku_num != target_sku_num or (
                    hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp'))):
                if end_pack_type != PackType.ZX.value:
                    rt.target_pack_type = PackType.ZX.value
                    warning_msg = f'[PC] 任务包规修正 (自制一楼纸箱多DC 默认不换包) task: {rt.task_id} target_pack_type: {end_pack_type} -> {rt.target_pack_type}'
                    logger.warning(warning_msg)
                    end_pack_type = rt.target_pack_type
        # 自制逻辑校验路径
        zz_filter_route_list = []
        for r in route_list:
            if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type and r.end_pack_type == end_pack_type:
                # 自制 非自制
                if storer_layer.is_zz():
                    # 自制场景 只能走route的remark=(1, -1)字段 走1楼 还是-1楼
                    if r.remark != storer_layer.flag():
                        continue
                else:
                    # 非自制场景 只能走非自制路径
                    if r.is_zz():
                        continue
                zz_filter_route_list.append(r)
        # 包规及PCS数校验
        for r in zz_filter_route_list:
            # 最终包规为 自制箱时，需判断是否需要去GTP。
            if r.end_pack_type == PackType.ZZX.value:
                # ----------------- 当前栈板只会有: 1.栈板直发; 2.栈板PTX任务 ----------------> 理论上 不会再走这块的逻辑了
                # 起始包规为 栈板时
                if start_pack_type == PackType.ZB.value:
                    error_msg = f'[PC] 路径选择 task: {rt.task_id} 任务数据异常。1栈板 -> 3自制箱 ?'
                    logger.error(error_msg)
                    # PCS数不同，并且最终PCS数 无法由几个整件箱满足时，肯定要去GTP 即is_mpq==1
                    if origin_sku_num != target_sku_num and target_sku_num % int(casecant) != 0:
                        if r.is_mpq != '1':
                            continue
                    # PCS数相同，或者最终PCS数, 肯定不会去GTP 即is_mpq!=1
                    if origin_sku_num == target_sku_num or target_sku_num % int(casecant) == 0:
                        if r.is_mpq == '1':
                            continue
                # 起始包规为纸箱时
                elif start_pack_type == PackType.ZX.value:
                    # PCS数不同时，一定去GTP  或者  多DC场景有拣选
                    if origin_sku_num != target_sku_num or (
                            hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp')):
                        if r.is_mpq != '1':
                            continue
                    # PCS数相同时 且 多DC场景总PCS数与act_num相同时(即ext_force_gtp != True)，一定不去GTP
                    if origin_sku_num == target_sku_num and not hasattr(rt, 'ext_force_gtp'):
                        if r.is_mpq == '1':
                            continue
                # 起始包规为自制箱时
                elif start_pack_type == PackType.ZZX.value:
                    # PCS数不同时，一定去GTP  或者  多DC场景有拣选
                    if origin_sku_num != target_sku_num or (
                            hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp')):
                        if r.is_mpq != '1':
                            continue
                    # PCS数相同时，一定不去GTP 且 多DC场景总PCS数与act_num相同时(即ext_force_gtp != True)，一定不去GTP
                    if origin_sku_num == target_sku_num and not hasattr(rt, 'ext_force_gtp'):
                        if r.is_mpq == '1':
                            continue
            match_route.append(r)

    #
    if not match_route:
        warning_msg = (f'[PC] [发货] 路径找不到！command_type_code:{command_type_code}, task: {rt.task_id}, '
                       f'start_pack_type:{start_pack_type}, end_pack_type:{end_pack_type}, '
                       f'origin_sku_num:{origin_sku_num}, target_sku_num:{target_sku_num}, '
                       f'storer_layer:{storer_layer.flag()}')
        logger.warning(warning_msg)
        return None
    # 过滤可用路径
    filtered_match_route = [_ for _ in match_route if _.ext_isvalid]
    if not filtered_match_route:
        route_errors_str = '\n'.join([f'\t({_.id}[{_.name}])' for _ in match_route])
        error_msg = f'[PC] [发货] 无可用路径！task: {rt.task_id}, 已匹配但不可用路径: \n{route_errors_str}'
        logger.error(error_msg)
        return None
    if len(filtered_match_route) > 1:
        debug_msg = (f'[PC] [发货] 多条路径可选！command_type_code:{command_type_code}, task: {rt.task_id}, '
                     f'start_pack_type:{start_pack_type}, end_pack_type:{end_pack_type}, '
                     f'origin_sku_num:{origin_sku_num}, target_sku_num:{target_sku_num}')
        logger.debug(debug_msg)
    # 若多种路径 随机选择一个
    r = random.choice(filtered_match_route)
    info_msg = f'[PC] [发货] 路径选择 task: {rt.task_id}, route: {r.id}({r.name}), 其余可选route: [{", ".join([f"{_.id}({_.name})" for _ in filtered_match_route if _ != r])}]'
    logger.info(info_msg)
    return r


def interior_route_choice(rt: InteriorWorkQueue, route_list: list[CommandRoute], logger: Logger,
                          all_dc_lpns_dict: dict[tuple[str, str], list[tuple[str, str, int]]]):
    """
    在库 路径选择
    :param rt:
    :param route_list:
    :param logger:
    :param all_dc_lpns_dict: 多DC LPN
    :return:
    """
    # 指令类型
    command_type_code: str = rt.command_type_code
    # 开始包装类型
    start_pack_type: int = rt.origin_pack_type

    # PCS数
    act_num: int = rt.act_num
    target_sku_num: int = rt.target_sku_num

    # dc lpn
    dc_lpn = (rt.command_group_code, rt.lpn)
    # 多DC 需拣选
    ext_force_gtp = hasattr(rt, 'ext_force_gtp') and getattr(rt, 'ext_force_gtp')

    # 匹配的路径
    match_route = []

    # 根据 指令类型及初始包规，进行初步判断
    for r in route_list:
        if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type:
            match_route.append(r)

    # 件箱盘点
    if command_type_code == CommandTypeCode.INV_CHECK.value:
        if start_pack_type == PackType.ZX.value:
            if rt.has_out():
                match_route = [r for r in match_route if r.is_out()]
            else:
                match_route = [r for r in match_route if not r.is_out()]

    # 栈板出 分 (整体 / 部分)
    if command_type_code in (CommandTypeCode.SKU_TRF.value, CommandTypeCode.REP_TASK_ZBS.value):
        # 仅栈板出库场景 需要判断
        if start_pack_type == PackType.ZB.value:
            real_target_sku_num = target_sku_num
            # 处理 多DC场景
            if dc_lpn in all_dc_lpns_dict:
                lpns = all_dc_lpns_dict[dc_lpn]
                real_target_sku_num = sum([_[-1] for _ in lpns if isinstance(_, tuple) and len(_) == 3])
            # 处理 非多DC场景
            if act_num == real_target_sku_num:
                match_route = [r for r in match_route if r.end_pack_type == PackType.ZB.value]
            else:
                match_route = [r for r in match_route if r.end_pack_type == PackType.ZX.value]

    #
    if command_type_code == CommandTypeCode.REP_TASK_SPLIT.value:
        # 根据是否需要拣选 过滤路径
        need_gtp = (dc_lpn not in all_dc_lpns_dict and act_num > target_sku_num) or (
                dc_lpn in all_dc_lpns_dict and ext_force_gtp)
        if need_gtp:
            match_route = [r for r in match_route if r.is_mpq == '1']
        else:
            match_route = [r for r in match_route if not r.is_mpq == '1']

    # 结果及日志
    if not match_route:
        warning_msg = (f'[PC] [在库] 路径找不到! command_type_code: {command_type_code}, task: {rt.task_id}, '
                       f'start_pack_type: {start_pack_type}, is_out: {rt.is_out}')
        logger.warning(warning_msg)
        return None

    # 过滤可用路径
    filtered_match_route = [_ for _ in match_route if _.ext_isvalid]
    if not filtered_match_route:
        route_errors_str = '\n'.join([f'\t({_.id}[{_.name}])' for _ in match_route])
        error_msg = f'[PC] [在库] 无可用路径！task: {rt.task_id}, 已匹配但不可用路径: \n{route_errors_str}'
        logger.error(error_msg)
        return None

    # 随机选择路径
    # 若多种路径 随机选择一个
    r = random.choice(filtered_match_route)

    # 多DC处理  设置/限制修正
    if dc_lpn in all_dc_lpns_dict:
        if isinstance(all_dc_lpns_dict[dc_lpn][-1], tuple):
            all_dc_lpns_dict[dc_lpn].append(r)
            pass
        else:
            # 同LPN 已选择的路径
            mr = all_dc_lpns_dict[dc_lpn][-1]
            if mr in filtered_match_route:
                r = mr

    # XXX: 将原始任务的最终包规 与任务的最终包规同步
    rt.target_pack_type = r.end_pack_type
    info_msg = f'[PC] [在库] 路径选择 task: {rt.task_id}, route: {r.id}({r.name}), 其余可选route: [{", ".join([f"{_.id}({_.name})" for _ in filtered_match_route if _ != r])}]'
    logger.info(info_msg)
    return r


def prework_route_choice(rt: PreworkWorkQueue, route_list: list[CommandRoute], logger: Logger):
    # 指令类型
    command_type_code: str = rt.command_type_code
    # 开始包装类型
    start_pack_type: int = rt.origin_pack_type

    # PCS数
    act_num: int = rt.act_num
    target_sku_num: int = rt.target_sku_num

    # 匹配的路径
    match_route = []

    # 根据 指令类型及初始包规，进行初步判断
    for r in route_list:
        if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type:
            match_route.append(r)

    # 结果及日志
    if not match_route:
        warning_msg = (f'[PC] [预作业] 路径找不到! command_type_code: {command_type_code}, task: {rt.task_id}, '
                       f'start_pack_type: {start_pack_type}')
        logger.warning(warning_msg)
        return None
    # 过滤可用路径
    filtered_match_route = [_ for _ in match_route if _.ext_isvalid]
    if not filtered_match_route:
        route_errors_str = '\n'.join([f'\t({_.id}[{_.name}])' for _ in match_route])
        error_msg = f'[PC] [预作业] 无可用路径！task: {rt.task_id}, 已匹配但不可用路径: \n{route_errors_str}'
        logger.error(error_msg)
        return None

    # 若多种路径 随机选择一个
    r = random.choice(filtered_match_route)
    info_msg = f'[PC] [预作业] 路径选择 task: {rt.task_id}, route: {r.id}({r.name}), 其余可选route: [{", ".join([f"{_.id}({_.name})" for _ in filtered_match_route if _ != r])}]'
    logger.info(info_msg)
    return r


def tally_route_choice(rt: PreworkWorkQueue, route_list: list[CommandRoute], logger: Logger):
    # 指令类型
    command_type_code: str = rt.command_type_code
    # 开始包装类型
    start_pack_type: int = rt.origin_pack_type

    # PCS数
    act_num: int = rt.act_num
    target_sku_num: int = rt.target_sku_num

    # 匹配的路径
    match_route = []

    # 根据 指令类型及初始包规，进行初步判断
    for r in route_list:
        if r.command_type_code == command_type_code and r.start_pack_type == start_pack_type:
            match_route.append(r)

    # 结果及日志
    if not match_route:
        warning_msg = (f'[PC] [理货] 路径找不到! command_type_code: {command_type_code}, task: {rt.task_id}, '
                       f'start_pack_type: {start_pack_type}')
        logger.warning(warning_msg)
        return None
    # 过滤可用路径
    filtered_match_route = [_ for _ in match_route if _.ext_isvalid]
    if not filtered_match_route:
        route_errors_str = '\n'.join([f'\t({_.id}[{_.name}])' for _ in match_route])
        error_msg = f'[PC] [理货] 无可用路径！task: {rt.task_id}, 已匹配但不可用路径: \n{route_errors_str}'
        logger.error(error_msg)
        return None

    # 若多种路径 随机选择一个
    r = random.choice(filtered_match_route)
    info_msg = f'[PC] [理货] 路径选择 task: {rt.task_id}, route: {r.id}({r.name}), 其余可选route: [{", ".join([f"{_.id}({_.name})" for _ in filtered_match_route if _ != r])}]'
    logger.info(info_msg)
    return r
